package com.xiezc.dht.message;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Set;

import com.xiezc.dht.model.BeList;
import com.xiezc.dht.model.BeMap;
import com.xiezc.dht.model.BeObject;
import com.xiezc.dht.model.BeString;
import com.xiezc.dht.util.BeException;
import com.xiezc.dht.util.Const;
import com.xiezc.dht.util.XUtil;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.xiezc.dht.message.MessageBuild.*;

public class RespMsgBuild {

    BeMap beMap;
    BeMap r = new BeMap();

    BeList rValues = new BeList();

    public RespMsgBuild(BeMap beMap) {
        this.beMap = beMap;
    }

    public RespMsgBuild buildRId(BeString str) {
        r.put(id, str);
        return this;
    }

    public RespMsgBuild buildRToken(String str) {
        r.put(token, new BeString(str));
        return this;
    }

    public RespMsgBuild buildT(BeString target) {
        beMap.put(t, target);
        return this;
    }

    public RespMsgBuild buildRNodes(BeString str) {
        r.put(nodes, str);
        return this;
    }

    public RespMsgBuild buildRValues(List<BeObject> str) {
        r.put(values, new BeList(str));
        return this;
    }

    public Message buildPingResp(InetSocketAddress socketAddress) {
        beMap.put(MessageBuild.r, r);

        Set<BeObject> keySet = beMap.getValue().keySet();

        if (!keySet.contains(t)) {
            buildT(new BeString("xz"));
        }
        if (!keySet.contains(y)) {
            beMap.put(y, MessageBuild.r);
        }
        if (!keySet.contains(MessageBuild.r)) {
            beMap.put(MessageBuild.r, r);
        }
        if (!r.getValue().keySet().contains(id)) {
            throw new BeException("r中的id的值未设置");
        }
        Message message = new Message();
        message.setBeMap(beMap);
        message.setMsgTypeEnum(MsgTypeEnum.resp_ping);
        message.setSocketAddress(socketAddress);

        return message;

    }

    public Message buildPingResp(String ip, int port) {
        return buildPingResp(new InetSocketAddress(ip, port));
    }

    public Message buildRespFindNode(String ip, int port) {
        return buildRespFindNode(new InetSocketAddress(ip, port));
    }

    public Message buildRespFindNode(InetSocketAddress socketAddress) {
        beMap.put(MessageBuild.r, r);

        Set<BeObject> keySet = beMap.getValue().keySet();

        if (!keySet.contains(t)) {
            buildT(new BeString("xz"));
        }
        if (!keySet.contains(y)) {
            beMap.put(y, MessageBuild.r);
        }

        if (!keySet.contains(MessageBuild.r)) {
            beMap.put(MessageBuild.r, r);
        }
        if (!r.getValue().keySet().contains(id)) {
            r.put(id, Const.thisId);
        }
        if (!r.getValue().keySet().contains(nodes)) {
            throw new BeException("r中的nodes的值未设置");
        }

        Message message = new Message();
        message.setBeMap(beMap);
        message.setMsgTypeEnum(MsgTypeEnum.resp_findNode);
        message.setSocketAddress(socketAddress);
        return message;
    }

    public Message buildRespGetPeersOk(String ip, int port) {
        return buildRespGetPeersOk(new InetSocketAddress(ip, port));
    }

    public Message buildRespGetPeersNo(InetSocketAddress socketAddress) {
        beMap.put(MessageBuild.r, r);

        Set<BeObject> keySet = beMap.getValue().keySet();

        if (!keySet.contains(t)) {
            buildT(new BeString("xz"));
        }
        if (!keySet.contains(y)) {
            beMap.put(y, MessageBuild.r);
        }

        if (!keySet.contains(MessageBuild.r)) {
            beMap.put(MessageBuild.r, r);
        }
        if (!r.getValue().keySet().contains(id)) {
            r.put(id, Const.thisId);
        }
        if (!r.getValue().keySet().contains(nodes)) {
            throw new BeException("r中的nodes的值未设置");
        }
        if (!r.getValue().keySet().contains(token)) {
            throw new BeException("r中的token的值未设置");
        }

        Message message = new Message();
        message.setBeMap(beMap);
        message.setMsgTypeEnum(MsgTypeEnum.resp_getPeers);
        message.setSocketAddress(socketAddress);
        return message;
    }

    public Message buildRespGetPeersNo(String ip, int port) {
        return buildRespGetPeersNo(new InetSocketAddress(ip, port));
    }

    public Message buildRespGetPeersOk(InetSocketAddress socketAddress) {
        beMap.put(MessageBuild.r, r);

        Set<BeObject> keySet = beMap.getValue().keySet();

        if (!keySet.contains(t)) {
            buildT(new BeString("xz"));
        }
        if (!keySet.contains(y)) {
            beMap.put(y, MessageBuild.r);
        }

        if (!keySet.contains(MessageBuild.r)) {
            beMap.put(MessageBuild.r, r);
        }
        if (!r.getValue().keySet().contains(id)) {
            r.put(id, Const.thisId);
        }
        if (!r.getValue().keySet().contains(values)) {
            throw new BeException("r中的values的值未设置");
        }
        if (!r.getValue().keySet().contains(token)) {
            r.put(token, new BeString(XUtil.getRandomToken()));
        }

        Message message = new Message();
        message.setBeMap(beMap);
        message.setMsgTypeEnum(MsgTypeEnum.resp_getPeers);
        message.setSocketAddress(socketAddress);

        return message;
    }

}
